<template>
  <el-container class="setting-panel-container">
    <el-tabs v-model="activeTab" style="height: 100%;width: 100%;overflow: hidden">
      <!-- 组件设置 -->
      <el-tab-pane :label="i18nt('designer.hint.widgetSetting')" name="1">
        <el-scrollbar class="setting-scrollbar">
          <!-- 容器组件走这里 -->
          <template v-if="!!designer.selectedWidget && !designer.selectedWidget.category">
            <el-form :model="optionModel" size="small" label-position="left" label-width="118px" class="setting-form"
              @submit.prevent>
              <el-collapse v-model="widgetActiveCollapseNames" class="setting-collapse">
                <!-- 常见属性 -->
                <el-collapse-item name="1" v-if="showCollapse(commonProps)"
                  :title="i18nt('designer.setting.commonSetting')">
                  <template v-for="(editorName, propName) in commonProps" :key="propName">
                    <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                      :global-dsv="globalDsv"
                      :designer="designer" :selected-widget="selectedWidget" :option-model="optionModel"></component>
                  </template>
                </el-collapse-item>
                <!-- 组件样式 -->
                <el-collapse-item name="2" v-if="showCollapse(comStyleProps)"
                  :title="i18nt('designer.setting.comStyleSetting')">
                  <template v-for="(editorName, propName) in comStyleProps" :key="propName">
                    <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                      :global-dsv="globalDsv"
                      :designer="designer" :selected-widget="selectedWidget" :option-model="optionModel"></component>
                  </template>
                </el-collapse-item>
                <!-- 高级属性 -->
                <el-collapse-item name="3" v-if="showCollapse(advProps)"
                  :title="i18nt('designer.setting.advancedSetting')">
                  <template v-for="(editorName, propName) in advProps" :key="propName">
                    <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                      :global-dsv="globalDsv"
                      :designer="designer" :selected-widget="selectedWidget" :option-model="optionModel"></component>
                  </template>
                </el-collapse-item>
                <!-- 事件属性 -->
                <el-collapse-item name="4" v-if="showEventCollapse() && showCollapse(eventProps)"
                  :title="i18nt('designer.setting.eventSetting')">
                  <template v-for="(editorName, propName) in eventProps" :key="propName">
                    <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                      :global-dsv="globalDsv"
                      :designer="designer" :selected-widget="selectedWidget" :option-model="optionModel"
                      :event-handled="getEventHandled(propName)"></component>
                  </template>
                </el-collapse-item>

              </el-collapse>

            </el-form>
          </template>
          <!-- 字段组件走这里 -->
          <template v-if="(!!designer.selectedWidget && !!designer.selectedWidget.category)">
            <el-form :model="optionModel" size="small" label-position="left" label-width="118px" class="setting-form"
              @submit.prevent>
              <el-collapse v-model="widgetActiveCollapseNames" class="setting-collapse">
                <!-- 常见属性 -->
                <el-collapse-item name="1" v-if="showCollapse(commonProps)"
                  :title="i18nt('designer.setting.commonSetting')">
                  <template v-for="(editorName, propName) in commonProps" :key="propName">
                    <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                      :designer="designer" :selected-widget="selectedWidget" 
                      :global-dsv="globalDsv"
                      :option-model="optionModel"></component>
                  </template>
                </el-collapse-item>
                <!-- 组件样式 -->
                <el-collapse-item name="2" v-if="showCollapse(comStyleProps)"
                  :title="i18nt('designer.setting.comStyleSetting')">
                  <template v-for="(editorName, propName) in comStyleProps" :key="propName">
                    <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                      :designer="designer" :selected-widget="selectedWidget" 
                      :global-dsv="globalDsv"
                      :option-model="optionModel"></component>
                  </template>
                </el-collapse-item>
                <!-- 高级属性 -->
                <el-collapse-item name="3" v-if="showCollapse(advProps)"
                  :title="i18nt('designer.setting.advancedSetting')">
                  <template v-for="(editorName, propName) in advProps" :key="propName">
                    <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                      :designer="designer" :selected-widget="selectedWidget" 
                      :global-dsv="globalDsv"
                      :option-model="optionModel"></component>
                  </template>
                </el-collapse-item>
                <!-- 事件属性 -->
                <el-collapse-item name="4" v-if="showEventCollapse() && showCollapse(eventProps)"
                  :title="i18nt('designer.setting.eventSetting')">
                  <template v-for="(editorName, propName) in eventProps" :key="propName">
                    <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                      :global-dsv="globalDsv"
                      :designer="designer" :selected-widget="selectedWidget" :option-model="optionModel"
                      :event-handled="getEventHandled(propName)"></component>
                  </template>
                </el-collapse-item>

              </el-collapse>
            </el-form>
          </template>

          <template v-if="!designer.selectedWidget">
            <el-empty :description="i18nt('designer.hint.noSelectedWidgetHint')"></el-empty>
          </template>

        </el-scrollbar>
      </el-tab-pane>

      <!-- 全局设置 -->
      <el-tab-pane v-if="!!designer" :label="i18nt('designer.hint.formSetting')" name="2">
        <el-scrollbar class="setting-scrollbar">
          <form-setting :designer="designer" :form-config="formConfig"></form-setting>
        </el-scrollbar>
      </el-tab-pane>

      <el-tab-pane :label="i18nt('designer.setting.dataSource')" name="3">
        <el-scrollbar class="ds-setting-scrollbar">
          <data-source-setting :designer="designer" :form-config="formConfig">
          </data-source-setting>
        </el-scrollbar>
      </el-tab-pane>
    </el-tabs>

    <div v-if="showWidgetEventDialogFlag" class=""
      v-drag="['.drag-dialog.el-dialog', '.drag-dialog .el-dialog__header']">
      <el-dialog :title="i18nt('designer.setting.editWidgetEventHandler')" v-model="showWidgetEventDialogFlag"
        :show-close="true" class="drag-dialog small-padding-dialog" append-to-body :close-on-click-modal="false"
        :close-on-press-escape="false" :destroy-on-close="true">
        <el-alert type="info" :closable="false" :title="eventHeader"></el-alert>
        <code-editor :mode="'javascript'" :readonly="false" v-model="eventHandlerCode" ref="ecEditor"></code-editor>
        <el-alert type="info" :closable="false" title="}"></el-alert>
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="showWidgetEventDialogFlag = false">
              {{ i18nt('designer.hint.cancel') }}</el-button>
            <el-button type="primary" @click="saveEventHandler">
              {{ i18nt('designer.hint.confirm') }}</el-button>
          </div>
        </template>
      </el-dialog>
    </div>

  </el-container>
</template>

<script>
import CodeEditor from '@/components/code-editor/index'
import PropertyEditors from './property-editor/index'
import FormSetting from './form-setting'
import DataSourceSetting from './data-source-setting'
import WidgetProperties from './propertyRegister'
import {
  addWindowResizeHandler, widgetIsSubFormType,
} from "@/utils/util"
import i18n from "@/utils/i18n"
import emitter from "@/utils/emitter";
import { propertyRegistered } from "@/components/form-designer/setting-panel/propertyRegister";

const { COMMON_PROPERTIES, ADVANCED_PROPERTIES, EVENT_PROPERTIES, COMSTYLE_PROPERTIES } = WidgetProperties

export default {
  name: "SettingPanel",
  componentName: "SettingPanel",
  mixins: [i18n, emitter],
  components: {
    CodeEditor,
    FormSetting,
    DataSourceSetting,
    ...PropertyEditors,
  },
  props: {
    designer: Object,
    selectedWidget: Object,
    formConfig: Object,
    globalDsv: {
      type: Object,
      default: () => ({})
    },
  },
  provide() {
    return {
      isSubFormChildWidget: () => this.subFormChildWidgetFlag,
      getGlobalDsv: () => this.globalDsv, // 全局数据源变量
      parentWidget: () => this.parentWidget //父节点
    }
  },
  inject: ['getDesignerConfig', 'getFormtype'],
  data() {
    return {
      designerConfig: this.getDesignerConfig(),

      activeTab: "2",
      widgetActiveCollapseNames: ['1', '3'], //['1', '2', '3'],
      formActiveCollapseNames: ['1', '2'],

      commonProps: COMMON_PROPERTIES,
      advProps: ADVANCED_PROPERTIES,
      eventProps: EVENT_PROPERTIES,
      comStyleProps: COMSTYLE_PROPERTIES,
      showWidgetEventDialogFlag: false,
      eventHandlerCode: '',
      curEventName: '',
      eventHeader: '',

      subFormChildWidgetFlag: false,
      parentWidget: {}
    }
  },
  computed: {
    optionModel: {
      get() {
        return this.selectedWidget.options
      },

      set(newValue) {
        this.selectedWidget.options = newValue
      }
    },
  },
  watch: {
    'designer.selectedWidget': {
      handler(val) {
        if (!!val) {
          this.activeTab = "1"
        }
      }
    },

    'selectedWidget.options': {  //组件属性变动后，立即保存表单JSON！！
      deep: true,
      handler() {
        this.designer.saveCurrentHistoryStep()
      }
    },

    formConfig: {
      deep: true,
      handler() {
        this.designer.saveCurrentHistoryStep()
      }
    },

  },
  created() {
    this.on$('editEventHandler', (eventParams) => {
      this.editEventHandler(eventParams[0], eventParams[1])
    })

    this.designer.handleEvent('form-css-updated', (cssClassList) => {
      this.designer.setCssClassList(cssClassList)
    })

    //监听字段组件选中事件
    this.designer.handleEvent('field-selected', (parentWidget) => {
      this.parentWidget = parentWidget;
      this.subFormChildWidgetFlag = !!parentWidget && widgetIsSubFormType(parentWidget)
    })
  },
  mounted() {
    if (!this.designer.selectedWidget) {
      this.activeTab = "2"
    } else {
      this.activeTab = "1"
    }
  },
  methods: {
    getEventHandled(eventName) {
      return !!this.optionModel[eventName] && (this.optionModel[eventName].length > 0)
    },

    showEventCollapse() {
      if (this.designerConfig['eventCollapse'] === undefined) {
        return true
      }

      return !!this.designerConfig['eventCollapse']
    },

    hasPropEditor(propName, editorName) {
      if (!editorName) {
        return false
      }

      /* alert组件注册了两个type属性编辑器，跳过第一个type属性编辑器，只显示第二个alert-type属性编辑器！！ */
      if (propName.indexOf('-') <= -1) {
        let uniquePropName = this.selectedWidget.type + '-' + propName
        if (propertyRegistered(uniquePropName)) {
          return false
        }
      }

      let originalPropName = propName.replace(this.selectedWidget.type + '-', '')  //去掉组件名称前缀-，如果有的话！！
      return this.designer.hasConfig(this.selectedWidget, originalPropName)
    },

    getPropEditor(propName, editorName) {
      let originalPropName = propName.replace(this.selectedWidget.type + '-', '')  //去掉组件名称前缀-，如果有的话！！
      let ownPropEditorName = `${this.selectedWidget.type}-${originalPropName}-editor`
      //console.log(ownPropEditorName, this.$options.components[ownPropEditorName])
      if (!!this.$options.components[ownPropEditorName]) {  //局部注册的属性编辑器组件
        return ownPropEditorName
      }

      //return !!this.$root.$options.components[ownPropEditorName] ? ownPropEditorName : editorName  //Vue2全局注册的属性编辑器组件
      return !!this.$root.$.appContext.components[ownPropEditorName] ? ownPropEditorName : editorName  //Vue3全局注册的属性编辑器组件
    },

    showCollapse(propsObj) {
      let result = false

      for (let propName in propsObj) {
        if (!propsObj.hasOwnProperty(propName)) {
          continue
        }

        if (this.hasPropEditor(propName, propsObj[propName])) {
          result = true
          break
        }
      }
      if (this.designer.widgetList.length > 0 && Object.keys(propsObj).includes('comStyle')) {
        result = true
      }
      return result
    },

    editEventHandler(eventName, eventParams) {
      this.curEventName = eventName
      this.eventHeader = `${this.optionModel.name}.${eventName}(${eventParams.join(', ')}) {`
      this.eventHandlerCode = this.selectedWidget.options[eventName] || ''

      // 设置字段校验函数示例代码
      if ((eventName === 'onValidate') && (!this.optionModel['onValidate'])) {
        this.eventHandlerCode = "  /* sample code */\n  /*\n  if ((value > 100) || (value < 0)) {\n    callback(new Error('error message'))  //fail\n  } else {\n    callback();  //pass\n  }\n  */"
      }

      this.showWidgetEventDialogFlag = true
    },

    saveEventHandler() {
      const codeHints = this.$refs.ecEditor.getEditorAnnotations()
      let syntaxErrorFlag = false
      if (!!codeHints && (codeHints.length > 0)) {
        codeHints.forEach((chItem) => {
          if (chItem.type === 'error') {
            syntaxErrorFlag = true
          }
        })

        if (syntaxErrorFlag) {
          this.$confirm(this.i18nt('designer.setting.syntaxCheckWarning'), this.i18nt('render.hint.prompt'), {
            confirmButtonText: this.i18nt('render.hint.forcedSave'),
            cancelButtonText: this.i18nt('render.hint.cancel')
          }).then(() => {
            this.selectedWidget.options[this.curEventName] = this.eventHandlerCode
            this.showWidgetEventDialogFlag = false
          }).catch(error => {
            //
          })

          return
        }
      }

      this.selectedWidget.options[this.curEventName] = this.eventHandlerCode
      this.showWidgetEventDialogFlag = false
    },

  }
}
</script>

<style lang="scss" scoped>
.setting-scrollbar {
  height: 100%;
  :deep(.el-scrollbar__wrap) {
    overflow-x: hidden; /* IE浏览器隐藏水平滚动条箭头！！ */
  }
}

.ds-setting-scrollbar {
  /*width: 284px;*/
  :deep(.el-scrollbar__wrap) {
    overflow-x: hidden; /* IE浏览器隐藏水平滚动条箭头！！ */
  }
}

.setting-collapse {
  :deep(.el-collapse-item:last-child) {
    margin-bottom: 48px;  /* 解决element-plus某些版本折叠面板内容未全部展示的问题 */
  }
  
  :deep(.el-collapse-item__content) {
    padding-bottom: 6px;
  }

  :deep(.el-collapse-item__header) {
    font-style: italic;
    font-weight: bold;
  }
}

.setting-form {
  :deep(.el-form-item__label) {
    font-size: 13px;
    //text-overflow: ellipsis;
    // overflow: hidden;
    white-space: wrap;
    line-height: 1 !important;
  }

  :deep(.el-form-item--small.el-form-item) {
    margin-bottom: 10px;
  }
}

/* 隐藏Chrome浏览器中el-input数字输入框右侧的上下调整小箭头 */
:deep(.hide-spin-button) input::-webkit-outer-spin-button,
:deep(.hide-spin-button) input::-webkit-inner-spin-button {
  -webkit-appearance: none !important;
}

/* 隐藏Firefox浏览器中el-input数字输入框右侧的上下调整小箭头 */
:deep(.hide-spin-button) input[type="number"] {
  -moz-appearance: textfield;
}

:deep(.custom-divider.el-divider--horizontal) {
  margin: 10px 0;
}

:deep(.custom-divider-margin-top.el-divider--horizontal) {
  margin: 20px 0;
}

.small-padding-dialog {
  :deep(.el-dialog__body) {
    padding: 6px 15px 12px 15px;
  }
}

:deep(.header-small-mb .el-drawer__header) {
  margin-bottom: 6px;
}

:deep(.header-small-mb .el-drawer__body) {
  padding: 12px;
}

:deep(.el-button.button-text-highlight) {
  font-weight: bold;
  color: $--color-primary;
}
</style>

<style lang="scss">
.ds-setting-drawer {
  right: 320px !important;
}
</style>
